package com.ff.kvm.common.third_util;

import cn.hutool.core.util.XmlUtil;
import com.ff.kvm.common.dv.payment.PaymentResult;
import com.ff.kvm.common.dv.payment.WXPayDV;
import com.ff.kvm.common.eunm.StatusEnum;
import com.ff.kvm.common.util.ConvertUtil;
import com.ff.kvm.common.util.MyUtil;
import com.ff.kvm.common.util.UuidUtil;
import com.ff.kvm.common.vo.Response;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;

public class WXPayUtil {

    private static String app_secret = "caabe27c0eed427afa8cd3171e9adf10";//密钥
    private static String app_key = "7C1C6E4B6386583930BF29C7EE5D074B";
    private static String appid = "wxdf844bbba0df4c36";//应用ID
    private static String mch_id = "1521489101";//商户号
    private static String nonce_str;//随机字符串
    private static String trade_type = "APP";//交易类型
//    private static String notify_url = "http://wqadxmm.xicp.net:37388/payResult/wx";//通知地址(测试环境)
        private static String notify_url = "http://47.96.148.139/kvm/payResult/wx";//通知地址(测试环境)


    private static String create_pre_order_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";//提交预支付订单地址

    public static Response<PaymentResult> createPreOrder(WXPayDV wxPayDV){
        return preWXPayDV(wxPayDV);
    }

    private static Response<PaymentResult> preWXPayDV(WXPayDV wxPayDV) {
        Response<PaymentResult> response = new Response<>();
        wxPayDV.setAppid(appid);
        wxPayDV.setMch_id(mch_id);
        wxPayDV.setNotify_url(notify_url);
        wxPayDV.setTrade_type(trade_type);
        wxPayDV.setNonce_str(UuidUtil.uuid32());
        //签名
        sign(wxPayDV);
        String rt = xmlHttpProxy(create_pre_order_url,toXmlBody(wxPayDV),"UTF-8");
        Map<String,String> map = ConvertUtil.xmlToMap(rt);
        if(!map.get("return_code").equals("SUCCESS") || !map.get("result_code").equals("SUCCESS")){

            response.setCode(map.get("return_code"));
            response.setMsg(map.get("return_msg"));
            return response;
        }
        response.setData(appSign(map));
        response.setCode(StatusEnum.SUCCESS.code());
        response.setMsg(StatusEnum.SUCCESS.description());
        return response;
    }

    private static PaymentResult appSign(Map<String,String> map) {
        PaymentResult result = new PaymentResult();
        result.setNoncestr(UuidUtil.uuid32());
        result.setPartnerid(mch_id);
        result.setPrepayid(map.get("prepay_id"));
        result.setTimestamp(new Date().getTime()/1000+"");
        StringBuffer sb = new StringBuffer();

        //按照格式拼接，微信规定
        sb.append("appid=").append(appid);
        sb.append("&noncestr=").append(result.getNoncestr());
        sb.append("&package=").append("Sign=WXPay");
        sb.append("&partnerid=").append(mch_id);
//        sb.append("&sign_type=").append("HMAC-SHA256");
        sb.append("&prepayid=").append(result.getPrepayid());
        sb.append("&timestamp=").append(result.getTimestamp());
        sb.append("&key=").append(app_key);

        result.setSign(MyUtil.MD5encode(sb.toString()).toUpperCase());
//        result.setSign(MyUtil.HMACSHA256(sb.toString(),app_key).toUpperCase());//HMAC-SHA256签名方式

        return result;
    }


    private static String toXmlBody(WXPayDV wxPayDV) {
        StringBuffer xml = new StringBuffer();
        xml.append("<xml>");
        xml.append("<appid>").append(wxPayDV.getAppid()).append("</appid>");
        xml.append("<mch_id>").append(wxPayDV.getMch_id()).append("</mch_id>");
        xml.append("<out_trade_no>").append(wxPayDV.getOut_trade_no()).append("</out_trade_no>");
//        xml.append("<sign_type>").append("HMAC-SHA256").append("</sign_type>");
        xml.append("<nonce_str>").append(wxPayDV.getNonce_str()).append("</nonce_str>");
        xml.append("<sign>").append(wxPayDV.getSign()).append("</sign>");
        xml.append("<body>").append(wxPayDV.getBody()).append("</body>");
        xml.append("<total_fee>").append(wxPayDV.getTotal_fee()).append("</total_fee>");
        xml.append("<spbill_create_ip>").append(wxPayDV.getSpbill_create_ip()).append("</spbill_create_ip>");
        xml.append("<notify_url>").append(wxPayDV.getNotify_url()).append("</notify_url>");
        xml.append("<trade_type>").append(wxPayDV.getTrade_type()).append("</trade_type>");
        xml.append("</xml>");


        return xml.toString();
//        return "<xml><appid><![CDATA[wxdf844bbba0df4c36]]></appid><body><![CDATA[康丽美购物]]></body><mch_id><![CDATA[1521489101]]></mch_id><nonce_str><![CDATA[3BF5B126B3E34F619537C3CEA5E0F4C]]></nonce_str><notify_url><![CDATA[http://wqadxmm.xicp.net:37388/payResult/wx]]></notify_url><out_trade_no><![CDATA[KVMRC201812221959101BEE]]></out_trade_no><sign_type><![CDATA[HMAC-SHA256]]></sign_type><spbill_create_ip><![CDATA[222.211.206.141]]></spbill_create_ip><total_fee><![CDATA[1]]></total_fee><trade_type><![CDATA[APP]]></trade_type><sign>C8B403B3E8D45EF4E1345165D7BA61A7A98A55478192452195F398DFD21FA311</sign></xml>";
    }

    private static void sign(WXPayDV wxPayDV) {
        StringBuffer sb = new StringBuffer();
        //按照格式拼接，微信规定
        sb.append("appid=").append(wxPayDV.getAppid());
        sb.append("&body=").append(wxPayDV.getBody());
        sb.append("&mch_id=").append(wxPayDV.getMch_id());
        sb.append("&nonce_str=").append(wxPayDV.getNonce_str());
        sb.append("&notify_url=").append(wxPayDV.getNotify_url());
        sb.append("&out_trade_no=").append(wxPayDV.getOut_trade_no());
//        sb.append("&sign_type=").append("HMAC-SHA256");
        sb.append("&spbill_create_ip=").append(wxPayDV.getSpbill_create_ip());
        sb.append("&total_fee=").append(wxPayDV.getTotal_fee());
        sb.append("&trade_type=").append(wxPayDV.getTrade_type());
        sb.append("&key=").append(app_key);

        wxPayDV.setSign(MyUtil.MD5encode(sb.toString()).toUpperCase());//md5签名方式
//        wxPayDV.setSign(MyUtil.HMACSHA256(sb.toString(),app_key).toUpperCase());//HMAC-SHA256签名方式
    }

    public static String xmlHttpProxy(String url,String xml,String contentType){
        InputStream is = null;
        OutputStreamWriter os = null;

        try {
            URL _url = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) _url.openConnection();
            conn.setDoInput(true);
            conn.setDoOutput(true);
            conn.setRequestProperty("Content-type", "text/xml");
//            conn.setRequestProperty("Pragma:", "no-cache");
            conn.setRequestProperty("Cache-Control", "no-cache");
            conn.setRequestMethod("POST");
            os = new OutputStreamWriter(conn.getOutputStream());
            os.write(new String(xml.getBytes(contentType)));
            os.flush();

            //返回值
            is = conn.getInputStream();
            return getContent(is, "utf-8");
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally{
            try {
                if(os!=null){os.close();}
                if(is!=null){is.close();}
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }


    public static String getContent(InputStream is, String charset) {
        String pageString = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        StringBuffer sb = null;
        try {
            isr = new InputStreamReader(is, charset);
            br = new BufferedReader(isr);
            sb = new StringBuffer();
            String line = null;
            while ((line = br.readLine()) != null) {
                sb.append(line + "\n");
            }
            pageString = sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null){
                    is.close();
                }
                if(isr!=null){
                    isr.close();
                }
                if(br!=null){
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            sb = null;
        }
        return pageString;
    }


    public static boolean checkSign(Map<String,String> params) {

        Set<String> keySet = params.keySet();
        String[] keyArray = keySet.toArray(new String[keySet.size()]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder();
        for (String k : keyArray) {
            if (k.equals("sign")) {
                continue;
            }
            if (params.get(k).trim().length() > 0) // 参数值为空，则不参与签名
                sb.append(k).append("=").append(params.get(k).trim()).append("&");
        }
        sb.append("key=").append(app_key);

//        if(MyUtil.HMACSHA256(sb.toString(),app_key).toUpperCase().equals(params.get("sign"))){
//            return true;
//        }
        if(MyUtil.MD5encode(sb.toString()).toUpperCase().equals(params.get("sign"))){
            return true;
        }
        return false;

    }


    public static void main(String[] args){
//        WXPayDV wxPayDV = new WXPayDV();
//        wxPayDV.setSpbill_create_ip("222.211.206.141");
//        wxPayDV.setTotal_fee(1);
//        wxPayDV.setOut_trade_no("123214");
//        wxPayDV.setBody("测试");
//        createPreOrder(wxPayDV);
        String xml = "<xml><return_code><![CDATA[SUCCESS]]></return_code>\n" +
                "<return_msg><![CDATA[OK]]></return_msg>\n" +
                "<appid><![CDATA[wxdf844bbba0df4c36]]></appid>\n" +
                "<mch_id><![CDATA[1521489101]]></mch_id>\n" +
                "<nonce_str><![CDATA[J7hctR1vqdFtsdOY]]></nonce_str>\n" +
                "<sign><![CDATA[F8C250303CBC5D0F907A8FE104F08638]]></sign>\n" +
                "<result_code><![CDATA[SUCCESS]]></result_code>\n" +
                "<prepay_id><![CDATA[wx21225152893680d7204378963189518677]]></prepay_id>\n" +
                "<trade_type><![CDATA[APP]]></trade_type>\n" +
                "</xml>";
        Document doc = XmlUtil.readXML(xml.replace("\n",""));
        NodeList nodeList = doc.getFirstChild().getChildNodes();

        for (int i = 0;i<nodeList.getLength();i++){
            Node node = nodeList.item(i);
            System.out.println(node.getNodeName()+","+node.getFirstChild().getNodeValue());

        }

    }
}
